home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_12_01
/
letters
/
rpft.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-07
|
22KB
|
674 lines
/******************************************************
* RPFT.C -- Curve fitting with optional extrapolation.
* Fits either polynomial or rational function. Based
* on algorithms defined in Press, et al., "Numerical
* Recipes", 2nd ed., Cambridge University Press, 1992
* Developed using the Borland C compiler.
*
* To compile: bcc rpft.c
*
* Lowell Smith
* 3368 Crestwood Drive
* Salt Lake City, UT 84109-3202
*
* June 8, 1993
* 1) Corrected error in COMMD for reading command
* line -DIG value
* 2) Revised RATINT to eliminate occasional error
* interpolating exact polynomial data with a Y
* value (not the first or last point) of zero.
*****************************************************/
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <dir.h>
#include <ctype.h>
#include <stddef.h>
#include <stdlib.h>
#define NPFAC 8
#define PI 3.141592653589793
#define PIO2 (PI/2.0)
#define SIGN(a,b) ((b) > 0.0 ? fabs(a) : -fabs(a))
void ratlsq(double xs[],double fs[],int npt,int mm,
int kk, double cof[], double *dev);
double *dvector(long nl, long nh, const char *ner);
double **dmatrix(long nrl,long nrh,long ncl,long nch,
const char *ner);
void free_dvector(double *v, long ncl);
void free_dmatrix(double **m, long nrl, long ncl);
/*****************************************************/
void main(int argc, char **argv)
{ double a,b,*xs,*fs,cof[42],dev=0.,sumd,x,yy;
int i,j,nn,nd,ncof,dig,npt=0,xln,yln;
char nar[90];
char filenam[80];
void commd(int argc, char**argv, double *a,double *b,
int *nn, int *nd, int *dig, int *xln,
int *yln, char *filenam);
void inpt(int nn,int npt,double a, double b, int xln,
int yln, double *xs,double *fs,char filenam[]);
void pcshft(double a,double b,double d[],int n);
void chebpc(double c[],double d[],int n);
commd(argc,argv,&a,&b,&nn,&nd,&dig,&xln,&yln,
filenam);
if (xln) { a=log(a); b=log(b); }
if (nd) /* Fit rational function */
{ ncof=nn+nd+1; npt=NPFAC*ncof;
xs=dvector(1L,(long)npt,"xs in main");
fs=dvector(1L,(long)npt,"fs in main");
inpt(0, npt, a, b, xln, yln, xs, fs, filenam);
ratlsq(xs,fs,npt,nn,nd,&cof[0],&dev);
fprintf(stderr,"Est. max error = %.7G\n",dev);
free_dvector(xs,1L);
free_dvector(fs,1L);
}
else /* Fit polynomial */
{ ncof=nn+5; xs=dvector(0L,(long)ncof,"xs in main");
fs=dvector(0L,(long)ncof,"fs in main");
inpt(ncof, npt, a, b, xln, yln, xs, fs, filenam);
chebpc(fs,cof,nn+1);
pcshft(a,b,cof,nn+1);
free_dvector(xs,0L); free_dvector(fs,0L);
}
for (i=0;i<=nn+nd;++i)
{ sprintf(nar,"%.*G ",dig,cof[i]);
sscanf(nar,"%lf",&cof[i]);
}
if (nd) printf("\n Rational function coefficien"
"ts\n Numerator Denominator\n\n");
else printf("\n Polynomial\n Coefficients\n\n");
for (i=0;i<max(nd,nn)+1;++i)
{ if (i<=nn) printf("%-24.16G",cof[i]);
else printf("%*s",24," ");
if (i<nd) printf("%-24.16G\n",cof[i+nn+1]);
else printf("\n");
}
for(;;) /* Calculate trial values */
{ i=-1;
fprintf(stderr,
"Enter E to quit or a trial X value: ");
i=scanf("%lf",&x);
if (i<1) exit(1); if (xln) x=log(x);
yy=cof[nn]; for (j=nn-1;j>=0;j--) yy=yy*x+cof[j];
if (nd)
{ for (sumd=0.,j=nn+nd;j>=nn+1;j--)
sumd=(sumd+cof[j])*x;
yy=yy/(1.0+sumd);
}
if (yln) yy=exp(yy); if (xln) x=exp(x);
fprintf(stderr,"For X=%.8G Y=%.8G\n",x,yy);
}
}
/******************************************************
* COMMD - Parses the command line
*****************************************************/
void commd(int argc, char**argv, double *a,double *b,
int *nn, int *nd, int *dig, int *xln,
int *yln, char *filenam)
{ struct ffblk ffblk;
int i,j,k,l;
void help(char *msg);
*a=1.11e300; *b=-1.11e300; *nn=-32768; *nd=-32768;
*dig=7, *xln=0, *yln=0;
if (argc<2) help(""); filenam[0]=0;
for (i=1,k=0;i<argc;k=0,++i)
{ for (j=0; j<(l=strlen(argv[i])); ++j)
{ argv[i][j]=toupper(argv[i][j]);
if (argv[i][j]=='=') ++k;
}
if (k)
{ if (k>1 || (!isdigit(argv[i][l-1])
&& argv[i][l-1] !='.'))
{ fprintf(stderr,"Invalid command line parameter"
" %s\n",argv[i]);
help("");
}
if (!strncmp(argv[i],"LL=",3))
{ k=sscanf(&argv[i][3],"%lf",a);
if (k<1) help("Invalid value for command line"
" parameter LL\n"); continue;
}
if (!strncmp(argv[i],"UL=",3))
{ k=sscanf(&argv[i][3],"%lf",b);
if (k<1) help("Invalid value for command line"
" parameter UL\n"); continue;
}
if (!strncmp(argv[i],"ND=",3))
{ k=sscanf(&argv[i][3],"%d",nd);
if (k<1) help("Invalid value for command line"
" parameter ND\n"); continue;
}
if (!strncmp(argv[i],"NN=",3))
{ k=sscanf(&argv[i][3],"%d",nn);
if (k<1) help("Invalid value for command line"
" parameter NN\n"); continue;
}
if (!strncmp(&argv[i][0],"-DIG=",5))
{ k=sscanf(&argv[i][5],"%d",dig);
if (k<1) help("Invalid value for optional"
" command line parameter DIG\n");
continue;
}
fprintf(stderr,"Invalid command line parameter "
"%s\n",argv[i]);
help("");
}
else
{ if (!strncmp(&argv[i][0],"-XLN",4))
{ *xln=1; continue; }
if (!strncmp(&argv[i][0],"-YLN",4))
{ *yln=1; continue; }
if (!filenam[0] && argv[i][0] != '-')
{ strcpy(filenam,argv[i]);
if (findfirst(filenam,&ffblk,0))
{ fprintf(stderr,"Input file %s doesn't "
"exist\n",filenam); help("");
}
}
else
{ fprintf(stderr,"Invalid command line parameter"
" %s\n",argv[i]); help("");
}
}
}
k=0;
if (*a>1.1e300)
{ fprintf(stderr,"Parameter LL undefined\n"); ++k; }
if (*b<-1.1e300)
{ fprintf(stderr,"Parameter UL undefined\n"); ++k; }
if (*nn==-32768)
{ fprintf(stderr,"Parameter NN undefined\n"); ++k;
*nn=5;
}
if (*nd==-32768)
{ fprintf(stderr,"Parameter ND undefined\n"); ++k;
*nd=5;
}
if (filenam[0]==0)
{ fprintf(stderr,"Input file is not defined\n");
++k;
}
if (*nn<1 || (*nd==0 && *nn>20) || (*nd && *nn>10))
{ fprintf(stderr,"Invalid value %d for "
"command line parameter NN\n",*nn); ++k;
}
if (*nd<0 || *nd>10)
{ fprintf(stderr,"Invalid value %d for "
"command line parameter ND\n",*nd); ++k;
}
if (*a>*b)
{ fprintf(stderr,"Lower limit > upper limit\n");
++k;
}
if (*dig<1 || *dig>20)
{ fprintf(stderr,"Invalid value %d for "
"command line option DIG\n",*dig); ++k;
}
if (*xln && *a<=0.)
{ fprintf(stderr,"Lower limit is <=0 with "
"logarithmic transform of X values\n"); ++k;
}
if (k) help("");
}
/******************************************************
* HELP - Prints the help screen
*****************************************************/
void help(char *msg)
{ char *hlp[] =
{ "USAGE: rpft LL=a UL=b NN=n ND=m [-DIG=n -XLN -YLN"
"] file",""," LL=a a is the lower limit of the"
"region for fit"," UL=b b is the upper limit o"
"f the region for fit",""," ND=m | m>0: rational"
" function, denominator degree m,"," NN=n | "
" numerator degree n. 1<=m<=10 1<=n<=10"," "
" | m=0: Polynomial degree n. 1<=n<=20",""," -DI"
"G=n (optional) n = number of significant digits"
," for coefficients on output. Defaul"
"t=7."," -XLN (optional) Transform X values to"
" ln(X)"," -YLN (optional) Transform Y values "
"to ln(Y)",""," file File with input X Y data "
"points, 1 per line","","All command line paramete"
"rs except DIG, XLN and Y